<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>歌词滚动</title>

    <style>
        html {
            width: 100%;
            height: 100%;
        }
        body {
            margin: 0;
            background-color: black;
            color: gray;
            text-align: center;

            width: 100%;
            height: 100%;
            display: flex;
            flex-direction: column;
            justify-content: center;
            align-items: center;
        }

        a {
            color: white;
            text-decoration: none;
        }
        a:hover {
            cursor: pointer;
            color: blue;
        }

        .audio {
            margin-top: 5vh;
        }

        .container {
            width: 100%;
            display: flex;
            justify-content: space-around;
        }

        .list-song {
            display: flex;
            flex-direction: column;
            gap: 0.5em;
            text-align: left;
        }

        .list-lrc {
            flex: 1;
            list-style: none;

            overflow: auto;
            scroll-behavior: smooth;
            transition: .3s linear;

            padding: 0;
            margin: 0;
            height: 24em;
            display: flex;
            flex-direction: column;
            justify-content: flex-start;
            align-items: center;
            gap: 1em;
        }
        .list-lrc::-webkit-scrollbar {
            background-color: #aaa;;
            border-radius: 0.25rem;
        }
        .list-lrc::-webkit-scrollbar-thumb {
            background-color: #666;
            border-radius: 0.25rem;
        }
        .list-lrc::-webkit-scrollbar-button {
            display: none;
        }

        .list-lrc .list-item {
            user-select: none;
            transition: .2s;
        }

        .list-lrc .list-item.active {
            color: white;
            transform: scale(1.25);
        }
    </style>
</head>
<body>
    <div class="container">
        <div class="panel">
            <ul class="list-song">
                <li><a href="#忘了你忘了我" onclick="切歌('忘了你忘了我')">忘了你忘了我</a></li>
                <li><a href="#不浪漫罪名" onclick="切歌('不浪漫罪名')">不浪漫罪名</a></li>
            </ul>
        </div>
    </div>
    <audio id="audio" class="audio" src="忘了你忘了我.mp3" controls></audio>

    <script>
        function createDynamicLRCList(audioElement, lrcText) {

            /**
             * 解析歌词
             * @param {string} lrc
             * @returns {Array<{time: number, text: string}>}
             */
            function parseLRC(lrc) {
                return lrc.split("\n").map(item => {
                const [timeString, text] = item.split("]");
                const [minute, second] = timeString.slice(1).split(":");
                const time = parseInt(minute) * 60 + parseInt(second);
                    return {
                        time,
                        text: text.trim()
                    };
                });
            }

            /**
             * 寻找当前播放时间对应的歌词索引
             * @param {Array<{time: number, text: string}>} lrcList
             * @param {number} time
             * @returns {number}
             */
            function findIndex(lrcList, time) {
                for (let i = 0; i < lrcList.length; i++) {
                    const item = lrcList[i];
                    // 出现的第一个时间大于当前时间，返回上一个索引
                    if (time < item.time) {
                        return i - 1;
                    }
                }
                return -1;
            }

            /**
             * 滚动歌词列表
             * @param {HTMLUListElement} listElement
             * @param {number} itemIndex
             */
            function scrollList(listElement, itemIndex) {
                const li = listElement.querySelector(".active");
                if (li) {
                    li.classList.remove("active");
                }
                if (itemIndex < 0) {
                    listElement.scrollBy(0, 0);
                    return;
                }
                const currentElement = listElement.children[itemIndex];
                currentElement.classList.add("active");
                const listRectangle = listElement.getBoundingClientRect();
                const itemRectangle = currentElement.getBoundingClientRect();
                const offset = itemRectangle.top - listRectangle.top - listRectangle.height / 2.5;
                listElement.scrollBy(0, offset);
            }

            const lrcList = parseLRC(lrcText);
            const doms = {
                /** @type {HTMLAudioElement} */
                audioElement,
                /** @type {HTMLUListElement} */
                lrcListElement: (function(){
                    const list = document.createElement("ul");
                    list.classList.add("list-lrc");
                    return list;
                })(),
            }
            for(const item of lrcList) {
                const li = document.createElement("li");
                li.className = "list-item";
                li.textContent = item.text;

                li.onmouseover = () => {
                    if (!doms.audioElement.paused) {
                        li.style.cursor = "pointer";
                    }
                }
                li.onmouseout = () => {
                    li.style.cursor = "default";
                }
                li.onclick = () => {
                    doms.audioElement.currentTime = item.time;
                };
                doms.lrcListElement.appendChild(li);
            }

            let currentIndex = -1;
            doms.audioElement.ontimeupdate = (e) => {
                /** @type {HTMLAudioElement} */
                const audioElement = e.target;
                if (audioElement.paused) {
                    return;
                }
                const currentTime = audioElement.currentTime;
                const index = findIndex(lrcList, currentTime);
                if (index !== currentIndex) {
                    currentIndex = index;
                    scrollList(doms.lrcListElement, currentIndex);
                }
            };

            doms.lrcListElement.addEventListener("drop", () => {

            })

            return doms.lrcListElement;
        };

        async function 切歌(name) {
            const response = await fetch(name + ".lrc");
            const lrc = await response.text();
            console.log(lrc);
            const audioElement = document.querySelector(".audio");
            audioElement.src = name + ".mp3";

            const containerElement = document.querySelector(".container");
            let listElement = containerElement.querySelector(".list-lrc");
            if (listElement) {
                listElement.remove();
            }
            listElement = createDynamicLRCList(audioElement, lrc);
            containerElement.appendChild(listElement);
        }

        (async function() {
            await 切歌("忘了你忘了我");
        })();
    </script>
</body>
</html>
